#include "../source/server.hpp"

void HandleClose(Channel *channel)
{
    // std::cout << "fd close: " << channel->Fd() << std::endl;
    DLOG("fd close: %d", channel->Fd());
    // 移除监控
    channel->Remove();
    delete channel;
}

void HandleRead(Channel *channel)
{
    // 直接接收数据
    int fd = channel->Fd();
    char buffer[1024];
    ssize_t ret = recv(fd, buffer, 1023, 0); // 阻塞式接收
    if (ret <= 0)
    {
        return HandleClose(channel);
    }
    // 开启写事件
    channel->EnableWrite();
    // std::cout << "client# " << buffer << std::endl;
    DLOG("%s", buffer);
}

void HandleWrite(Channel *channel)
{
    int fd = channel->Fd();
    const char *str = "server# 中秋节快乐!";
    int ret = send(fd, str, strlen(str), 0);
    if (ret <= 0)
    {
        return HandleClose(channel);
    }
    // 关闭写事件
    channel->DisableWrite();
}

void HandleErr(Channel *channel)
{
    return HandleClose(channel);
}

void HandleEvent(EventLoop *loop, Channel *channel, uint64_t tid)
{
    // std::cout << "Have a Event!" << std::endl;
    // 当有任意事件来了，就刷新一下活跃度 延迟非活跃时间
    loop->TimerRefresh(tid);
}

void Acceptor(EventLoop *loop, Channel *lst_channel)
{
    int fd = lst_channel->Fd();
    int newfd = accept(fd, NULL, NULL);
    if (newfd < 0)
    {
        return;
    }
    uint64_t tid = rand() % 1000;
    Channel *channel = new Channel(loop, newfd);
    channel->SetReadCallBack(std::bind(HandleRead, channel)); // 设置回调函数
    channel->SetWriteCallBack(std::bind(HandleWrite, channel));
    channel->SetCloseCallBack(std::bind(HandleClose, channel));
    channel->SetErrCallBack(std::bind(HandleErr, channel));
    channel->SetEventCallBack(std::bind(HandleEvent, loop, channel, tid));
    // 在启动读事件之前，添加一个10s钟的非活跃的销毁任务
    loop->TimerAdd(tid, 10, std::bind(HandleClose, channel));
    channel->EnableRead(); // 启动读事件
}

int main()
{
    srand(time(NULL));
    EventLoop loop;
    Socket srv;
    srv.CreateServer(8880);
    srv.ReuseAddress();
    // 为监听套接字创建读回调，并创建Channel，设置回调函数
    Channel channel(&loop, srv.Fd());
    channel.SetReadCallBack(std::bind(Acceptor, &loop, &channel)); // 监听套接字，不断获取新连接，为新连接创建Channel并添加监控
    channel.EnableRead();                                          // 开启读监控监听套接字
    while (1)
    {
        loop.StartEventLoop();
    }
    srv.Close();
    return 0;
}